package common

import (
	"crypto/md5"
	"encoding/binary"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"gitee.com/kinwyb/conv"
	"math"
	"math/rand"
	"net"
	"reflect"
	"strconv"
	"strings"
	"time"
)

// 时间格式
const (
	DateFormat     = "2006-01-02"
	DateTimeFormat = "2006-01-02 15:04:05"
	TimeFormat     = "15:04:05"
)

var idGen = NewGenerator(uint16(rand.Uint32()>>16), time.Now())

// TimeNow 当前日期时间
func TimeNow() string {
	return time.Now().Format(DateTimeFormat)
}

// IDGen id生成器
func IDGen() string {
	id := idGen.Next()
	return strings.ToUpper(strconv.FormatUint(id, 32))
}

// IDGenUInt64 id生成
func IDGenUInt64() uint64 {
	return idGen.Next()
}

// DateTimeStringToDateStartTime 时间日期字符串时间改成00:00:00
func DateTimeStringToDateStartTime(dateTimeString string) string {
	return strings.Split(dateTimeString, " ")[0] + " 00:00:00"
}

// DateTimeStringToDateEndTime 时间日期字符串时间改成23:59:59
func DateTimeStringToDateEndTime(dateTimeString string) string {
	return strings.Split(dateTimeString, " ")[0] + " 23:59:59"
}

// TimeToDateStartTimeString 时间转换成当日起始时间字符串
func TimeToDateStartTimeString(t time.Time) string {
	return t.Format(DateFormat) + " 00:00:00"
}

// TimeToDateEndTimeString 时间转换成当日结束时间字符串
func TimeToDateEndTimeString(t time.Time) string {
	return t.Format(DateFormat) + " 23:59:59"
}

// EncryptoPassword 密码加密
func EncryptoPassword(password string, randString string) string {
	eBytes := append(MD5([]byte(password)), []byte(randString)...)
	return strings.ToUpper(hex.EncodeToString(MD5(eBytes)))
}

func MD5(key []byte) []byte {
	m := md5.New()
	m.Write(key)
	return m.Sum(nil)
}

func Int64ToBytes(i int64) []byte {
	var buf = make([]byte, 8)
	binary.BigEndian.PutUint64(buf, uint64(i))
	return buf
}

func BytesToInt64(buf []byte) int64 {
	return int64(binary.BigEndian.Uint64(buf))
}

// JsonData json数据
func JsonData(v interface{}) []byte {
	data, _ := json.Marshal(v)
	return data
}

// LocalIPv4 获取一个本地IP地址
func LocalIPv4() string {
	var ips []string
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return ""
	}
	var ip string
	for _, a := range addrs {
		if ipnet, ok := a.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
			networkSize, _ := ipnet.Mask.Size()
			if ipnet.Mask.String() == "255.255.255.0" ||
				ipnet.Mask.String() == "ffffff00" ||
				networkSize == 24 {
				ip = ipnet.IP.String()
				break
			}
			ips = append(ips, ipnet.IP.String())
		}
	}
	if ip != "" {
		return ip
	} else if len(ips) > 0 {
		return ips[0]
	}
	return ""
}

// Round 精确小数点后几位
func Round(num float64, decimals int) float64 {
	if decimals < 1 {
		return math.Round(num)
	}
	return conv.ToFloat64Default(fmt.Sprintf("%."+fmt.Sprintf("%d", decimals)+"f"), num)
}

// RemoveRepeatedString 数组去除重复
func RemoveRepeatedString(arr []string) (newArr []string) {
	newArr = make([]string, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		}
	}
	return
}

// RemoveRepeatedInt64 数组去除重复
func RemoveRepeatedInt64(arr []int64) (newArr []int64) {
	newArr = make([]int64, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		}
	}
	return
}

// TimeParse 时间转换
func TimeParse(layout, value string) (time.Time, error) {
	return time.ParseInLocation(layout, value, time.Local)
}

// ToString 字符串转换
func ToString(value interface{}, def ...string) string {
	if value == nil {
		return ""
	}
	defValue := ""
	if len(def) > 0 {
		defValue = def[0]
	}
	return strings.TrimSpace(conv.ToStringDefault(value, defValue))
}

// ToDateString 转换成日期字符串
func ToDateString(value interface{}) string {
	dateTimeString := ToString(value)
	return strings.Split(dateTimeString, " ")[0]
}

// SubString 截取字符串 start 起点下标 end 终点下标(不包括)
func SubString(str string, start int, end int) string {
	rs := []rune(str)
	length := len(rs)
	if start < 0 || start > length {
		return ""
	}
	if end < 0 || end > length {
		return ""
	}
	return string(rs[start:end])
}

// Clone 复制一个对象
type Clone interface {
	Clone() interface{}
}

func InterfaceClone(oldObj interface{}) interface{} {
	if newVal, ok := oldObj.(Clone); ok {
		return newVal.Clone()
	}
	newObj := reflect.New(reflect.TypeOf(oldObj).Elem())
	oldVal := reflect.ValueOf(oldObj).Elem()
	newVal := newObj.Elem()
	for i := 0; i < oldVal.NumField(); i++ {
		newValField := newVal.Field(i)
		if newValField.CanSet() {
			newValField.Set(oldVal.Field(i))
		}
	}
	return newObj.Interface()
}

// WhereIn sql组合
func WhereIn(values []string) (string, []interface{}) {
	sql := strings.Builder{}
	var args []interface{}
	for _, v := range values {
		sql.WriteString("?,")
		args = append(args, v)
	}
	return strings.TrimRight(sql.String(), ","), args
}

// Float64ToString 浮点数转换字符串,length小数点后面几位,默认是3位
func Float64ToString(f float64, length ...int64) string {
	if len(length) < 1 {
		length = []int64{3}
	}
	fmtStr := fmt.Sprintf("%%.%df", length[0])
	ret := strings.TrimRight(fmt.Sprintf(fmtStr, f), "0")
	return strings.TrimRight(ret, ".")
}
